package com.example.wryproject.service;

import ohos.aafwk.ability.Ability;
import ohos.aafwk.ability.DataAbilityHelper;
import ohos.aafwk.ability.FormBindingData;
import ohos.aafwk.ability.FormException;
import ohos.aafwk.ability.LocalRemoteObject;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.window.dialog.ToastDialog;
import ohos.app.Context;
import ohos.data.orm.Blob;
import ohos.data.orm.OrmContext;
import ohos.data.orm.OrmPredicates;
import ohos.data.resultset.ResultSet;
import ohos.event.intentagent.IntentAgent;
import ohos.event.intentagent.IntentAgentConstant;
import ohos.event.intentagent.IntentAgentHelper;
import ohos.event.intentagent.IntentAgentInfo;
import ohos.event.notification.NotificationRequest;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.global.resource.RawFileDescriptor;
import ohos.global.resource.Resource;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.common.Source;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.photokit.metadata.AVMetadataHelper;
import ohos.media.photokit.metadata.AVStorage;
import ohos.media.player.Player;
import ohos.rpc.IRemoteObject;
import ohos.utils.net.Uri;
import ohos.utils.zson.ZSONObject;

import com.example.wryproject.MusicAbility;
import com.example.wryproject.bean.ChartDataBean;
import com.example.wryproject.bean.LrcContent;
import com.example.wryproject.database.CardData;
import com.example.wryproject.database.MusicData;
import com.example.wryproject.database.PlayingIndex;
import com.example.wryproject.slice.MusicAbilitySlice;
import com.example.wryproject.utils.DatabaseUtils;
import com.example.wryproject.utils.LyricAnalysisUtil;
import com.example.wryproject.utils.ThreadUtil;

import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class MusicServiceAbility extends Ability {
    private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001100, "Demo");
    private static final String PATH1 = "resources/rawfile/the_secret_of_winter.mp3";
    private static final String PATH2 = "resources/rawfile/blue_and_white_porcelain.mp3";
    private static final String PATH3 = "resources/rawfile/the_world.mp3";
    private static final String PATH4 = "resources/rawfile/sea.mp3";
    private static final String[] musics = {PATH1, PATH2, PATH3, PATH4};
    private static final String[] signers = {"周传雄", "周杰伦", "张杰", "张雨生"};
    private static final String[] musicTitles = {"冬天的秘密", "青花瓷", "天下", "大海"};
    private static PlayCallback playCallback;
    private OrmContext ormContext;
    private static MusicRemoteObject remoteObject;
    private static EventHandler eventHandler;
    private static List<LrcContent> lrcContents;
    private List<String> colorList;
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private int maximumPoolSize;
    private MusicRemoteObject.PlayerCallback myPlayerCallback;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        maximumPoolSize = CPU_COUNT * 2 + 1;
        ormContext = DatabaseUtils.getOrmContext(this);
        if (DatabaseUtils.queryAllMusicData(ormContext) == null
            || DatabaseUtils.queryAllMusicData(ormContext).isEmpty()) {
            loadLocalMusic();
        }
        remoteObject = new MusicRemoteObject(this);
    }

    @Override
    protected void onActive() {
        super.onActive();
    }

    /**
     * 加载本地音频数据
     */
    private void loadLocalMusic() {
        DataAbilityHelper helper = DataAbilityHelper.creator(this);
        try {
            ResultSet resultSet = helper.query(AVStorage.Audio.Media.EXTERNAL_DATA_ABILITY_URI, null, null);
            //通过while循环拿到所有音频数据
            while (resultSet != null && resultSet.goToNextRow()) {
                //音乐ID
                int musicId = resultSet.getInt(resultSet.getColumnIndexForName(AVStorage.AVBaseColumns.ID));
                //音频地址
                String musicPath = resultSet.getString(resultSet.getColumnIndexForName(AVStorage.AVBaseColumns.DATA));
                //音频名称
                String musicTitle = resultSet.getString(resultSet.getColumnIndexForName(AVStorage.AVBaseColumns.TITLE));
                //音频时长
                int musicDuration = resultSet.getInt(resultSet.getColumnIndexForName(AVStorage.AVBaseColumns.DURATION));
                //AVStorage自带属性中暂无歌手信息，但musicPath中包含歌手信息，此处将歌手名称截取出来
                int startIndex = musicPath.lastIndexOf("/");
                int endIndex = musicPath.lastIndexOf("-");
                String singer = "未知歌手";
                if (startIndex != -1 && endIndex != -1) {
                    if (endIndex < startIndex) {
                        endIndex = musicPath.lastIndexOf(".");
                    }
                    singer = musicPath.substring(startIndex + 1, endIndex - 1);
                }
                //过滤小于10秒的音频
                if (musicDuration > 10000) {
                    //将音频数据插入数据库
                    MusicData musicData = new MusicData();
                    musicData.setMusicId(musicId);
                    musicData.setMusicPath(musicPath);
                    musicData.setMusicTitle(musicTitle);
                    musicData.setMusicDuration(musicDuration);
                    musicData.setSinger(singer);
                    musicData.setMusicCover(null);
                    DatabaseUtils.insertMusicData(musicData, ormContext, getContext());
                }
            }
            resultSet.close();
            loadRawMusic();
            ThreadUtil.runWork(this::loadMusicCover);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 加载项目音频数据
     */
    private void loadRawMusic() {
        for (int i = 0; i < musics.length; i++) {
            String musicPath = musics[i];
            String singer = signers[i];
            String musicTitle = musicTitles[i];

            //将音频数据插入数据库
            MusicData musicData = new MusicData();
            musicData.setMusicId(i);
            musicData.setMusicPath(musicPath);
            musicData.setMusicTitle(musicTitle);
            musicData.setSinger(singer);
            musicData.setMusicCover(null);
            DatabaseUtils.insertMusicData(musicData, ormContext, getContext());
        }
    }

    /**
     * 读取raw音乐的流数据
     *
     * @param resource 音频文件
     * @return 字节流
     */
    private byte[] readInputStream(Resource resource) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int length = -1;
        try {
            while ((length = resource.read(buffer)) != -1) {
                baos.write(buffer, 0, length);
            }
            baos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        byte[] data = baos.toByteArray();
        try {
            resource.close();
            baos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return data;
    }

    /**
     * 获取音频封面
     */
    private void loadMusicCover() {
        DataAbilityHelper helper = DataAbilityHelper.creator(this);
        List<MusicData> musicDataList = DatabaseUtils.queryAllMusicData(ormContext);
        int dataSize = musicDataList.size();

        //每条线程处理的任务数量
        int taskNumber = dataSize / maximumPoolSize;

        // 创建一个线程池
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(5, maximumPoolSize, 1, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));
        List<List<MusicData>> allList = new ArrayList<>();
        List<MusicData> cutList;

        //确定每个线程要执行的任务
        for (int i = 0; i < maximumPoolSize; i++) {
            if (i == maximumPoolSize - 1) {
                cutList = musicDataList.subList(taskNumber * i, dataSize);
            } else {
                cutList = musicDataList.subList(taskNumber * i, taskNumber * (i + 1));
            }
            allList.add(cutList);
        }

        //为每个线程分配任务集合
        for (List<MusicData> dataList : allList) {
            poolExecutor.execute(() -> {
                for (MusicData musicData : dataList) {
                    AVMetadataHelper avMetadataHelper = new AVMetadataHelper();
                    int musicId = musicData.getMusicId();
                    String stringId = String.valueOf(musicId);
                    String musicPath = musicData.getMusicPath();
                    FileDescriptor fileDescriptor = null;
                    if (musicPath.contains("resources/rawfile")) {
                        Resource resource;
                        String path;
                        try {
                            //读取raw文件
                            //<p>
                            //使用如下写法,avMetadataHelper.resolveImage()会等于空，无法获取音频封面
                            //RawFileDescriptor rawFileDescriptor = getResourceManager().getRawFileEntry(musicPath).openRawFile();
                            //avMetadataHelper.setSource(rawFileDescriptor.getFileDescriptor);
                            //avMetadataHelper.resolveImage();
                            resource = getResourceManager().getRawFileEntry(musicPath).openRawFile();
                            path = getApplicationContext().getFilesDir() + "/" + musicId + ".mp3";

                            //将raw文件下读取的音频文件保存至内部存储
                            FileOutputStream fileOutputStream = new FileOutputStream(path);
                            fileOutputStream.write(readInputStream(resource));
                            fileOutputStream.close();

                            //通过音乐path获取专辑封面(path不能有中文,否则会报错)
                            avMetadataHelper.setSource(path);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    } else {
                        Uri uri = Uri.appendEncodedPathToUri(AVStorage.Audio.Media.EXTERNAL_DATA_ABILITY_URI, stringId);
                        try {
                            fileDescriptor = helper.openFile(uri, "r");
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                        //通过文件描述符获取封面
                        avMetadataHelper.setSource(fileDescriptor);
                    }
                    byte[] data = avMetadataHelper.resolveImage();
                    if (data != null) {
                        DatabaseUtils.updateMusicData(musicId, ormContext, new Blob(data));
                    }
                    avMetadataHelper.release();
                    avMetadataHelper.close();
                }
            });
        }
    }

    /**
     * 获取主线程handler
     *
     * @return eventHandler
     */
    public static EventHandler getEventHandler() {
        if (eventHandler == null) {
            EventRunner eventRunner = EventRunner.getMainEventRunner();
            eventHandler = new EventHandler(eventRunner) {
                @Override
                protected void processEvent(InnerEvent event) {
                    super.processEvent(event);
                    if (event.object instanceof String) {
                        //如果返回的是字符串,就是无歌词数据
                        remoteObject.lrcLoading("暂无歌词数据");
                        lrcContents = null;
                    } else if (event.object instanceof List) {
                        lrcContents = (List<LrcContent>) event.object;
                    }
                }
            };
        }
        return eventHandler;
    }

    // 前台service
    private void notice() {
        int position = remoteObject.getCurrentPosition();
        String title = DatabaseUtils.queryMusicData(position, ormContext).getMusicTitle();
        String singer = DatabaseUtils.queryMusicData(position, ormContext).getSinger();

        // 创建通知
        NotificationRequest request = new NotificationRequest(this, 1005);
        NotificationRequest.NotificationPictureContent content = new NotificationRequest.NotificationPictureContent();
        String fgTitle = title + " - " + singer;
        content.setTitle(fgTitle);
        content.setAdditionalText(remoteObject.getIsPlay() ? "正在播放..." : "暂停播放...");
        content.setBigPicture(remoteObject.getPixelMapCover());
        NotificationRequest.NotificationContent notificationContent = new NotificationRequest.NotificationContent(content);
        request.setAlertOneTime(true);
        request.setGroupAlertType(NotificationRequest.GROUP_ALERT_TYPE_CHILD);
        request.setBigIcon(remoteObject.getPixelMapCover());
        request.setContent(notificationContent);
        request.setIntentAgent(startAbilityIntentAgent());

        // 绑定通知
        keepBackgroundRunning(1005, request);
    }

    // 前台服务点击跳转
    private IntentAgent startAbilityIntentAgent() {
        Intent intent = new Intent();
        Operation operation = new Intent.OperationBuilder()
            .withDeviceId("")
            .withBundleName(getBundleName())
            .withAbilityName(MusicAbility.class.getName())
            .build();
        intent.setOperation(operation);
        List<Intent> intentList = new ArrayList<>();
        intentList.add(intent);
        List<IntentAgentConstant.Flags> flags = new ArrayList<>();
        flags.add(IntentAgentConstant.Flags.UPDATE_PRESENT_FLAG);
        IntentAgentInfo paramsInfo = new IntentAgentInfo(200, IntentAgentConstant.OperationType.START_ABILITY, flags, intentList, null);
        IntentAgent intentAgent = IntentAgentHelper.getIntentAgent(this, paramsInfo);
        return intentAgent;
    }

    @Override
    public void onBackground() {
        super.onBackground();
        HiLog.info(LABEL_LOG, "MusicServiceAbility::onBackground");
    }

    @Override
    public void onStop() {
        super.onStop();
        if (remoteObject.getPlayer() != null) {
            remoteObject.player.stop();
            remoteObject.player.release();
            remoteObject.player = null;
        }
        eventHandler.removeAllEvent();
        cancelBackgroundRunning();
        HiLog.info(LABEL_LOG, "MusicServiceAbility::onStop");
    }

    @Override
    public void onCommand(Intent intent, boolean restart, int startId) {
        super.onCommand(intent, restart, startId);
    }

    @Override
    public IRemoteObject onConnect(Intent intent) {
        if (remoteObject == null) {
            remoteObject = new MusicRemoteObject(this);
        }
        return remoteObject;
    }

    public static MusicRemoteObject get() {
        return remoteObject;
    }

    @Override
    public void onDisconnect(Intent intent) {
    }

    public class MusicRemoteObject extends LocalRemoteObject {
        private final MusicServiceAbility musicService;
        public int currentPosition = -1;
        private OrmContext ormContext;
        private List<MusicData> musicDataList;
        private Player player;
        private Ability mContext;
        private String musicTitle;
        private String singerName;
        private String path;
        private Source source;
        private EventHandler eventHandler;
        private Timer timer;

        /**
         * 构造方法
         *
         * @param musicService 服务类对象
         */
        MusicRemoteObject(MusicServiceAbility musicService) {
            this.musicService = musicService;
            mContext = musicService;
            ormContext = DatabaseUtils.getOrmContext(musicService);
            musicDataList = DatabaseUtils.queryAllMusicData(ormContext);
            colorList = new ArrayList<>();
            colorList.add("#5F9B30FF");
            colorList.add("#5F00BFFF");
            colorList.add("#5F0000FF");
            colorList.add("#5FEE0000");
            colorList.add("#5FFFA500");
            colorList.add("#5F00FF00");
        }

        /**
         * 初始化player，拿到歌曲数据
         *
         * @param context 上下文
         */
        public void initPlayer(Context context) {
            if (getPlayer() == null) {
                myPlayerCallback = null;
                myPlayerCallback = new PlayerCallback();
                player = new Player(context);
                player.setPlayerCallback(myPlayerCallback);
            }
            playListener();
        }

        /**
         * 更新卡片播放进度
         *
         * @param progressValue 播放进度
         */
        private void setCardProgress(int progressValue) {
            Random random = new Random();
            List<ChartDataBean> chartDataBeans = new ArrayList<>();
            List<Integer> dataBeanList = new ArrayList<>();
            for (int i = 0; i < 6; i++) {
                int chartData = random.nextInt(1000);
                dataBeanList.add(chartData);
            }
            int colorIndex = random.nextInt(colorList.size());
            chartDataBeans.add(new ChartDataBean(dataBeanList, colorList.get(colorIndex)));
            ZSONObject zsonObject = new ZSONObject();
            zsonObject.put("progressValue", progressValue);
            zsonObject.put("barData", chartDataBeans);
            updateCard(zsonObject);
        }

        /**
         * 更新所有卡片
         */
        private void updateCard(ZSONObject zsonObject) {
            List<CardData> cardDataList = DatabaseUtils.queryAllCardData(ormContext);
            FormBindingData formBindingData = new FormBindingData(zsonObject);
            //遍历卡片列表更新所有卡片
            for (CardData cardData : cardDataList) {
                try {
                    updateForm(cardData.getCardId(), formBindingData);
                } catch (FormException e) {
                    DatabaseUtils.deleteCardData(cardData.getCardId(), ormContext);
                }
            }
        }

        /**
         * 更新所有卡片封面
         */
        public void updateCardCover() {
            List<PlayingIndex> playingIndices = DatabaseUtils.queryPlayingIndex(DatabaseUtils.getOrmContext(getContext()));
            if (playingIndices != null && !playingIndices.isEmpty() && currentPosition == -1) {
                currentPosition = playingIndices.get(0).getOldIndex();
                setSource();
                playMusic();
            }
            ZSONObject zsonObject = setCardData();
            List<CardData> cardDataList = DatabaseUtils.queryAllCardData(ormContext);
            FormBindingData formBindingData = new FormBindingData(zsonObject);
            if (getCardCover() != null) {
                int musicId = getMusicList().get(currentPosition).getMusicId();
                String picName = musicId + ".png";
                String picPath = "memory://" + picName;
                assert zsonObject != null;
                zsonObject.put("picName", picPath);
                formBindingData.addImageData(picName, getCardCover());
            } else {
                zsonObject.put("picName", "/common/music.png");
            }
            //遍历卡片列表更新所有卡片
            for (CardData cardData : cardDataList) {
                try {
                    updateForm(cardData.getCardId(), formBindingData);
                } catch (FormException e) {
                    DatabaseUtils.deleteCardData(cardData.getCardId(), ormContext);
                }
            }
        }

        /**
         * 更新所有卡片歌词
         *
         * @param contentList 歌词列表
         */
        public void updateCardLyric(List<LrcContent> contentList) {
            ZSONObject zsonObject = new ZSONObject();
            List<CardData> cardDataList = DatabaseUtils.queryAllCardData(ormContext);
            zsonObject.put("lyric", contentList);
            //遍历卡片列表更新所有卡片
            for (CardData cardData : cardDataList) {
                try {
                    updateForm(cardData.getCardId(), new FormBindingData(zsonObject));
                } catch (FormException e) {
                    DatabaseUtils.deleteCardData(cardData.getCardId(), ormContext);
                }
            }
        }

        /**
         * 设置卡片数据
         */
        private ZSONObject setCardData() {
            // 设置卡片页面需要的数据
            if (ormContext == null) {
                ormContext = DatabaseUtils.getOrmContext(musicService.getContext());
            }
            ZSONObject zsonObject = new ZSONObject();
            int position = getCurrentPosition();
            //如果player没有设置资源，直接return
            if (position == -1) {
                return null;
            } else {
                //player设置了资源，将卡片按钮点亮
                zsonObject.put("lastImage", "/common/last.png");
                zsonObject.put("nextImage", "/common/next.png");
            }
            //根据播放状态设置卡片播放或暂停
            if (getIsPlay()) {
                zsonObject.put("playImage", "/common/pause.png");
            } else {
                zsonObject.put("playImage", "/common/play.png");
            }
            //设置卡片title
            String title = DatabaseUtils.queryMusicData(position, ormContext).getMusicTitle();
            String singer = DatabaseUtils.queryMusicData(position, ormContext).getSinger();
            zsonObject.put("songName", title);
            zsonObject.put("singer", singer);
            return zsonObject;
        }

        /**
         * 播放进度的更新
         */
        private void playListener() {
            EventRunner mainEventRunner = EventRunner.getMainEventRunner();
            eventHandler = new EventHandler(mainEventRunner) {
                @Override
                protected void processEvent(InnerEvent event) {
                    super.processEvent(event);
                    double total = getPlayer().getDuration();
                    double current = event.param;
                    double proportion = current / total * 100;
                    setCardProgress(Math.toIntExact(Math.round(proportion)));
                    if (lrcContents != null && !lrcContents.isEmpty()) {
                        for (int i = 0; i < lrcContents.size(); i++) {
                            LrcContent lrcContent = lrcContents.get(i);
                            LrcContent next = i + 1 == lrcContents.size() ? null : lrcContents.get(i + 1);
                            if ((current >= lrcContent.getLrcTime() && next != null && current < next.getLrcTime())
                                || (current > lrcContent.getLrcTime() && next == null)) {
                                List<LrcContent> contentList = new ArrayList<>();
                                for (int j = 0; j < 5; j++) {
                                    int index = i - (2 - j);
                                    if (index >= 0 && index < lrcContents.size()) {
                                        LrcContent content = lrcContents.get(index);
                                        if (j == 2) {
                                            content.setFontColor("#000000");
                                            content.setFontSize("16px");
                                        } else {
                                            content.setFontColor("#9C9C9C");
                                            content.setFontSize("14px");
                                        }
                                        contentList.add(content);
                                    } else {
                                        contentList.add(new LrcContent());
                                    }
                                }
                                updateCardLyric(contentList);
                            }
                        }
                    }
                }
            };
            if (timer != null) {
                timer.cancel();
                timer = null;
            }
            timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    if (getPlayer() != null && getPlayer().isNowPlaying()) {
                        InnerEvent innerEvent = InnerEvent.get();
                        innerEvent.param = getPlayer().getCurrentTime();
                        eventHandler.sendEvent(innerEvent);
                    }
                }
            }, 0, 200);
        }

        /**
         * 播放音乐
         */
        public void playMusic() {
            if (currentPosition == -1) {
                randomPlayer(musicDataList.size());
            } else if (player.isNowPlaying()) {
                player.pause();
            } else {
                player.play();
            }
            musicService.notice();
            if (MusicAbilitySlice.getProvider() != null) {
                ThreadUtil.runUI(() -> MusicAbilitySlice.getProvider()
                    .updatePlayerState(-1, currentPosition, player.isNowPlaying()));
            }
        }

        /**
         * 播放上一曲
         */
        public void lastMusic() {
            if (currentPosition == -1) {
                //未设置歌曲资源弹出dialog提示
                new ToastDialog(mContext)
                    .setAlignment(LayoutAlignment.CENTER)
                    .setText("请选择需要播放的歌曲~")
                    .show();
            } else if (currentPosition == 0) {
                //提示用户已经是第一首了
                new ToastDialog(mContext)
                    .setAlignment(LayoutAlignment.CENTER)
                    .setText("已经是第一首了~")
                    .show();
            } else {
                //播放上一首
                currentPosition -= 1;
                setSource();
            }
        }

        /**
         * 播放下一曲
         */
        public void nextMusic() {
            if (currentPosition == musicDataList.size() - 1) {
                //提示用户已经是最后一首了
                new ToastDialog(mContext)
                    .setAlignment(LayoutAlignment.CENTER)
                    .setText("已经是最后一首了~")
                    .show();
            } else if (currentPosition == -1) {
                //未设置歌曲资源弹出dialog提示
                new ToastDialog(mContext)
                    .setAlignment(LayoutAlignment.CENTER)
                    .setText("请选择要播放的歌曲~")
                    .show();
            } else {
                //播放下一曲
                currentPosition += 1;
                setSource();
            }
        }

        /**
         * 根据传入的数值区间，生成随机数，并播放
         *
         * @param end 随机数的最大区间
         */
        public void randomPlayer(int end) {
            Random random = new Random();
            currentPosition = random.nextInt(end);
            setSource();
        }

        /**
         * 重置播放器，设置资源重新播放
         */
        public void setSource() {
            musicTitle = musicDataList.get(currentPosition).getMusicTitle();
            singerName = musicDataList.get(currentPosition).getSinger();
            path = musicDataList.get(currentPosition).getMusicPath();
            if (lrcContents != null) {
                lrcContents.clear();
            }
            lrcLoading("歌词加载中...");
            LyricAnalysisUtil.getMusicLyric(musicTitle, singerName);

            //一个Player对象多次设置资源后,callback回调就不走了,此处每次设置资源都使用了新的Player对象
            if (getPlayer() != null) {
                player.stop();
                player.release();
                player = null;
            }
            initPlayer(musicService.getContext());

            //判断地址是raw文件下资源还是本地资源
            if (path.contains("resources/rawfile")) {
                RawFileDescriptor rawFileDescriptor;
                try {
                    rawFileDescriptor = getResourceManager().getRawFileEntry(path).openRawFileDescriptor();
                    player.setSource(rawFileDescriptor);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                source = new Source(path);
                player.setSource(source);
            }
            player.prepare();
            player.play();

            //开启前台服务
            musicService.notice();

            //更新卡片封面
            updateCardCover();
            if (MusicAbilitySlice.getProvider() != null) {
                ThreadUtil.runUI(() -> {
                    //更新列表播放状态
                    int oldPosition = -1;
                    List<PlayingIndex> indexList = DatabaseUtils.queryPlayingIndex(ormContext);
                    if (!indexList.isEmpty()) {
                        oldPosition = indexList.get(0).getOldIndex();
                    }
                    MusicAbilitySlice.getProvider().updatePlayerState(oldPosition, currentPosition, player.isNowPlaying());
                    DatabaseUtils.insertPlayingIndex(new PlayingIndex(currentPosition), ormContext);
                });
            }

            //设置播放接口回调
            if (playCallback != null) {
                playCallback.player();
            }
        }

        /**
         * 未加载出歌词时显示加载中
         */
        public void lrcLoading(String msg) {
            List<LrcContent> contentList = new ArrayList<>();
            for (int j = 0; j < 5; j++) {
                LrcContent lrcContent = new LrcContent();
                if (j == 2) {
                    lrcContent.setLrc(msg);
                    lrcContent.setFontColor("#9C9C9C");
                    lrcContent.setFontSize("18px");
                } else {
                    lrcContent.setLrc("");
                }
                contentList.add(lrcContent);
            }
            updateCardLyric(contentList);
        }

        /**
         * 通过MP3文件的数据流获取专辑封面
         *
         * @return 封面
         */
        public byte[] getCardCover() {
            OrmContext ormContext = DatabaseUtils.getOrmContext(getContext());
            OrmPredicates ormPredicates = ormContext.where(MusicData.class);
            List<MusicData> musicDataList = ormContext.query(ormPredicates);
            MusicData musicData = musicDataList.get(currentPosition);
            Blob musicCover = musicData.getMusicCover();
            byte[] bytes = null;
            if (musicCover != null && musicCover.length() != 0) {
                bytes = musicCover.getBytes(1, Math.toIntExact(musicCover.length()));
            }
            return bytes;
        }

        /**
         * 通过MP3文件的数据流获取专辑封面
         *
         * @return 封面
         */
        public PixelMap getPixelMapCover() {
            OrmContext ormContext = DatabaseUtils.getOrmContext(getContext());
            OrmPredicates ormPredicates = ormContext.where(MusicData.class);
            List<MusicData> musicDataList = ormContext.query(ormPredicates);
            MusicData musicData = musicDataList.get(currentPosition);
            Blob musicCover = musicData.getMusicCover();
            PixelMap pixelMap = null;
            if (musicCover != null && musicCover.length() != 0) {
                byte[] bytes = musicCover.getBytes(1, Math.toIntExact(musicCover.length()));
                ImageSource imageSource = ImageSource.create(bytes, null);

                //普通解码createPixelMap传入的DecodingOptions 设置为null
                pixelMap = imageSource.createPixelmap(null);
            }
            return pixelMap;
        }

        /**
         * 获取歌曲信息列表
         *
         * @return 歌曲信息列表
         */
        public List<MusicData> getMusicList() {
            return musicDataList;
        }

        /**
         * 获取歌曲名称
         *
         * @return 歌曲名称
         */
        public String getTitle() {
            return musicTitle;
        }

        /**
         * 获取歌手名称
         *
         * @return 歌手名称
         */
        public String getSingerName() {
            return singerName;
        }

        /**
         * 获取当前歌曲下标
         *
         * @return 当前歌曲下标
         */
        public int getCurrentPosition() {
            return currentPosition;
        }

        /**
         * 获取player对象
         *
         * @return player对象
         */
        public Player getPlayer() {
            return player;
        }

        /**
         * 获取是否在播放
         *
         * @return 是否播放
         */
        public boolean getIsPlay() {
            if (player != null) {
                return player.isNowPlaying();
            }
            return false;
        }

        /**
         * player状态回掉
         */
        class PlayerCallback implements Player.IPlayerCallback {
            @Override
            public void onPrepared() {
            }

            @Override
            public void onMessage(int type, int extra) {
            }

            @Override
            public void onError(int errorType, int errorCode) {
            }

            @Override
            public void onResolutionChanged(int i, int i1) {
            }

            @Override
            public void onPlayBackComplete() {
                player = null;
                randomPlayer(musicDataList.size());
            }

            @Override
            public void onRewindToComplete() {
            }

            @Override
            public void onBufferingChange(int i) {
            }

            @Override
            public void onNewTimedMetaData(Player.MediaTimedMetaData mediaTimedMetaData) {
            }

            @Override
            public void onMediaTimeIncontinuity(Player.MediaTimeInfo mediaTimeInfo) {
            }
        }
    }

    /**
     * 设置回调接口
     *
     * @param callback 回调接口
     */
    public static void setCallback(PlayCallback callback) {
        playCallback = callback;
    }

    /**
     * 开始播放的回调
     */
    public interface PlayCallback {
        void player();
    }
}